﻿using System;
using System.Reflection;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using DXP;
using PCB;
//using ContentTeamTools.Properties;

namespace ContentTeamTools
{
    public partial class MapMechLayersDialog : Form
    {
        public MapMechLayersDialog()
        {
            InitializeComponent();
        }

        private enum MechanicalLayer
        {
            Mechanical1 = 1,
            Mechanical2,
            Mechanical3,
            Mechanical4,
            Mechanical5,
            Mechanical6,
            Mechanical7,
            Mechanical8,
            Mechanical9,
            Mechanical10,
            Mechanical11,
            Mechanical12,
            Mechanical13,
            Mechanical14,
            Mechanical15,
            Mechanical16,
            Mechanical17,
            Mechanical18,
            Mechanical19,
            Mechanical20,
            Mechanical21,
            Mechanical22
        }

        private Dictionary<MechanicalLayer, MechanicalLayer> MechanicalLayerMap = new Dictionary<MechanicalLayer, MechanicalLayer>();

        private static class IMechanicalLayerSetting
        {
            public static MechanicalLayer TopDesginator = MechanicalLayer.Mechanical10;
            public static MechanicalLayer BottomDesginator = MechanicalLayer.Mechanical11;
            public static MechanicalLayer Top3dBody = MechanicalLayer.Mechanical13;
            public static MechanicalLayer Bottom3dBody = MechanicalLayer.Mechanical14;
            public static MechanicalLayer TopCourtyard = MechanicalLayer.Mechanical15;
            public static MechanicalLayer BottomCourtyard = MechanicalLayer.Mechanical16;
            public static MechanicalLayer TopCeneter = MechanicalLayer.Mechanical17;
            public static MechanicalLayer BottomCenter = MechanicalLayer.Mechanical18;
            public static MechanicalLayer TopAssembly = MechanicalLayer.Mechanical19;
            public static MechanicalLayer BottomAssembly = MechanicalLayer.Mechanical20;
            public static MechanicalLayer TopValue = MechanicalLayer.Mechanical21;
            public static MechanicalLayer BottomValue = MechanicalLayer.Mechanical22;
        }

        private void MapMechanicalLayerDialog_Load(object sender, EventArgs e)
        {
            cbDesignatorTop.Text = IMechanicalLayerSetting.TopDesginator.ToString();
            cbDesignatorTop.Items.AddRange(Enum.GetNames(typeof(MechanicalLayer)));

            cbDesignatorBottom.Text = IMechanicalLayerSetting.BottomDesginator.ToString();
            cbDesignatorBottom.Items.AddRange(Enum.GetNames(typeof(MechanicalLayer)));

            cbBodyTop.Text = IMechanicalLayerSetting.Top3dBody.ToString();
            cbBodyTop.Items.AddRange(Enum.GetNames(typeof(MechanicalLayer)));

            cbBodyBottom.Text = IMechanicalLayerSetting.Bottom3dBody.ToString();
            cbBodyBottom.Items.AddRange(Enum.GetNames(typeof(MechanicalLayer)));

            cbCourtyardTop.Text = IMechanicalLayerSetting.TopCourtyard.ToString();
            cbCourtyardTop.Items.AddRange(Enum.GetNames(typeof(MechanicalLayer)));

            cbCourtyardBottom.Text = IMechanicalLayerSetting.BottomCourtyard.ToString();
            cbCourtyardBottom.Items.AddRange(Enum.GetNames(typeof(MechanicalLayer)));

            cbCenterTop.Text = IMechanicalLayerSetting.TopCeneter.ToString();
            cbCenterTop.Items.AddRange(Enum.GetNames(typeof(MechanicalLayer)));

            cbCenterBottom.Text = IMechanicalLayerSetting.BottomCenter.ToString();
            cbCenterBottom.Items.AddRange(Enum.GetNames(typeof(MechanicalLayer)));

            cbAssemblyTop.Text = IMechanicalLayerSetting.TopAssembly.ToString();
            cbAssemblyTop.Items.AddRange(Enum.GetNames(typeof(MechanicalLayer)));

            cbAssemblyBottom.Text = IMechanicalLayerSetting.BottomAssembly.ToString();
            cbAssemblyBottom.Items.AddRange(Enum.GetNames(typeof(MechanicalLayer)));

            cbValueTop.Text = IMechanicalLayerSetting.TopValue.ToString();
            cbValueTop.Items.AddRange(Enum.GetNames(typeof(MechanicalLayer)));

            cbValueBottom.Text = IMechanicalLayerSetting.BottomValue.ToString();
            cbValueBottom.Items.AddRange(Enum.GetNames(typeof(MechanicalLayer)));

            //this.txtFootprintPath.Text = Settings.Default.FootprintsFolder;
        }


        private void btMap_Click(object sender, EventArgs e)
        {
            IClient client = DXP.GlobalVars.Client;
            string[] footprints = Directory.GetFiles(txtFootprintPath.Text, "*.PcbLib");
            foreach (string footprint in footprints)
            {
                IServerDocument pcbDocument = client.OpenDocument("PCBLIB", footprint);
                client.ShowDocumentDontFocus(pcbDocument);
                IPCB_ServerInterface pcbServer = PCB.GlobalVars.PCBServer;

                pcbServer.PreProcess();
                IPCB_Board currentBoard = pcbServer.GetCurrentPCBBoard();
                InitialMechanicalLayersSetting(currentBoard);
                //ActiveLayers(currentBoard, Enum.GetValues(typeof(MechanicalLayer)).Cast<int>().Select(t => V7_Layer.MechanicalLayer((ulong)t)).ToArray());

                IPCB_Library pcbLibrary = pcbServer.GetCurrentPCBLibrary();
                IPCB_LibraryIterator libIterator = pcbLibrary.LibraryIterator_Create();
                libIterator.AddFilter_ObjectSet(new PCB.TObjectSet(PCB.TObjectId.eComponentObject));
                IPCB_LibComponent pcbCmp = libIterator.FirstPCBObject() as IPCB_LibComponent;
                while (pcbCmp != null)
                {
                    //foreach (MechanicalLayer dest in this.MechanicalLayerMap.Keys)
                    //{
                    //    MoveFootprintPrimitives(pcbCmp, MechanicalLayerMap[dest], dest);
                    //}
                    MoveFootprintPrimitives(pcbCmp);
                    pcbCmp = libIterator.NextPCBObject() as IPCB_LibComponent;
                }
                pcbServer.PostProcess();
                currentBoard.GraphicalView_ZoomRedraw();
                pcbLibrary.LibraryIterator_Destroy(ref libIterator);
                pcbDocument.DoSafeFileSave("PCBLIB");
            }

            DXP.Utils.ShowMessage("Primitives moved");

            //Settings.Default.FootprintsFolder = this.txtFootprintPath.Text;
            //Settings.Default.Save();
        }

        private void ActiveLayers(IPCB_Board PCB_Board, V7_Layer[] Layers)
        {
            foreach (V7_Layer layer in Layers)
            {
                IPCB_MechanicalLayer layerObj = PCB_Board.GetState_LayerStack_V7().GetState_LayerObject_V7(layer) as IPCB_MechanicalLayer;
                layerObj.SetState_MechLayerEnabled(true);
                PCB_Board.SetState_LayerIsDisplayed(layer, true);
            }
        }

        private void InitialMechanicalLayersSetting(IPCB_Board PCB_Board)
        {
            foreach (FieldInfo info in typeof(IMechanicalLayerSetting).GetFields())
            {
                int n = (int)info.GetValue(null);
                V7_Layer layer = V7_Layer.MechanicalLayer((ulong)n);
                IPCB_MechanicalLayer layerObj = PCB_Board.GetState_LayerStack_V7().GetState_LayerObject_V7(layer) as IPCB_MechanicalLayer;
                layerObj.SetState_MechLayerEnabled(true);
                layerObj.SetState_LayerName(info.Name);
                PCB_Board.SetState_LayerIsDisplayed(layer, true);
            }
        }

        private void MoveFootprintPrimitives(IPCB_LibComponent pcbComponent)
        {
            List<PrimitiveMove> MoveTo = new List<PrimitiveMove>();
            foreach (MechanicalLayer dest in this.MechanicalLayerMap.Keys)
            {
                IPCB_GroupIterator pcbObjItera = pcbComponent.GroupIterator_Create();
                pcbObjItera.SetState_FilterAll();
                V7_LayerBase sourceLayer_V7 = V7_Layer.MechanicalLayer((ulong)MechanicalLayerMap[dest]);
                V7_LayerBase destLayer_V7 = V7_Layer.MechanicalLayer((ulong)dest);

                if (pcbObjItera.FirstPCBObject() == null) return;
                IPCB_Primitive pcbObj = pcbObjItera.FirstPCBObject() as IPCB_Primitive;
                while (pcbObj != null)
                {
                    if (pcbObj.GetState_V7Layer().ID == sourceLayer_V7.ID)
                    {
                        MoveTo.Add(new PrimitiveMove(pcbObj, destLayer_V7));
                    }
                    pcbObj = pcbObjItera.NextPCBObject() as IPCB_Primitive;
                }
                pcbComponent.GroupIterator_Destroy(ref pcbObjItera);
            }
            
            foreach (var obj in MoveTo)
            {
                obj.Move();
            }
        }


        private void cbDesignatorTop_SelectionChangeCommitted(object sender, EventArgs e)
        {
            ComboBox comboBox = sender as ComboBox;
            Enum.TryParse((string)comboBox.SelectedItem, out MechanicalLayer selectedlayer);
            this.MechanicalLayerMap[IMechanicalLayerSetting.TopDesginator] = selectedlayer;
        }

        private void cbDesignatorBottom_SelectionChangeCommitted(object sender, EventArgs e)
        {
            ComboBox comboBox = sender as ComboBox;
            Enum.TryParse((string)comboBox.SelectedItem, out MechanicalLayer selectedlayer);
            this.MechanicalLayerMap[IMechanicalLayerSetting.BottomDesginator] = selectedlayer;
        }
        private void cbBodyTop_SelectionChangeCommitted(object sender, EventArgs e)
        {
            ComboBox comboBox = sender as ComboBox;
            Enum.TryParse((string)comboBox.SelectedItem, out MechanicalLayer selectedlayer);
            this.MechanicalLayerMap[IMechanicalLayerSetting.Top3dBody] = selectedlayer;
        }
        private void cbBodyBottom_SelectionChangeCommitted(object sender, EventArgs e)
        {
            ComboBox comboBox = sender as ComboBox;
            Enum.TryParse((string)comboBox.SelectedItem, out MechanicalLayer selectedlayer);
            this.MechanicalLayerMap[IMechanicalLayerSetting.Bottom3dBody] = selectedlayer;
        }
        private void cbCenterTop_SelectionChangeCommitted(object sender, EventArgs e)
        {
            ComboBox comboBox = sender as ComboBox;
            Enum.TryParse((string)comboBox.SelectedItem, out MechanicalLayer selectedlayer);
            this.MechanicalLayerMap[IMechanicalLayerSetting.TopCeneter] = selectedlayer;
        }
        private void cbCenterBottom_SelectionChangeCommitted(object sender, EventArgs e)
        {
            ComboBox comboBox = sender as ComboBox;
            Enum.TryParse((string)comboBox.SelectedItem, out MechanicalLayer selectedlayer);
            this.MechanicalLayerMap[IMechanicalLayerSetting.BottomCenter] = selectedlayer;
        }
        private void cbAssemblyTop_SelectionChangeCommitted(object sender, EventArgs e)
        {
            ComboBox comboBox = sender as ComboBox;
            Enum.TryParse((string)comboBox.SelectedItem, out MechanicalLayer selectedlayer);
            this.MechanicalLayerMap[IMechanicalLayerSetting.TopAssembly] = selectedlayer;
        }
        private void cbAssemblyBottom_SelectionChangeCommitted(object sender, EventArgs e)
        {
            ComboBox comboBox = sender as ComboBox;
            Enum.TryParse((string)comboBox.SelectedItem, out MechanicalLayer selectedlayer);
            this.MechanicalLayerMap[IMechanicalLayerSetting.BottomAssembly] = selectedlayer;
        }
        private void cbValueTop_SelectionChangeCommitted(object sender, EventArgs e)
        {
            ComboBox comboBox = sender as ComboBox;
            Enum.TryParse((string)comboBox.SelectedItem, out MechanicalLayer selectedlayer);
            this.MechanicalLayerMap[IMechanicalLayerSetting.TopValue] = selectedlayer;
        }
        private void cbValueBottom_SelectionChangeCommitted(object sender, EventArgs e)
        {
            ComboBox comboBox = sender as ComboBox;
            Enum.TryParse((string)comboBox.SelectedItem, out MechanicalLayer selectedlayer);
            this.MechanicalLayerMap[IMechanicalLayerSetting.BottomValue] = selectedlayer;
        }
        private void cbCourtyardTop_SelectionChangeCommitted(object sender, EventArgs e)
        {
            ComboBox comboBox = sender as ComboBox;
            Enum.TryParse((string)comboBox.SelectedItem, out MechanicalLayer selectedlayer);
            this.MechanicalLayerMap[IMechanicalLayerSetting.TopCourtyard] = selectedlayer;
        }
        private void cbCourtyardBottom_SelectionChangeCommitted(object sender, EventArgs e)
        {
            ComboBox comboBox = sender as ComboBox;
            Enum.TryParse((string)comboBox.SelectedItem, out MechanicalLayer selectedlayer);
            this.MechanicalLayerMap[IMechanicalLayerSetting.BottomCourtyard] = selectedlayer;
        }

        public class PrimitiveMove
        {
            public IPCB_Primitive Obj;
            public V7_LayerBase DestLayer;
            public PrimitiveMove(IPCB_Primitive Primitive, V7_LayerBase Dest)
            {
                Obj = Primitive;
                DestLayer = Dest;
            }
            public void Move()
            {
                Obj.SetState_V7Layer(this.DestLayer);
            }
        }

    }
}
